﻿// <copyright file="Category.cs" company="Auros Ltd.">
//     Copyright (c) Auros Ltd. All rights reserved.
// </copyright>

namespace Auros.Categorisation
{
    using Auros.Categorisation.Data;
    using System;
    using System.Collections.Generic;
    using System.Linq;

    /// <summary>
    /// Class represents a single category.
    /// </summary>
    public class Category
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="Category"/> class.
        /// </summary>
        public Category()
        {
        }

        /// <summary>
        /// Gets the ID.
        /// </summary>
        /// <value>The ID of the category.</value>
        public int ID { get; internal set; }

        /// <summary>
        /// Gets or sets the name.
        /// </summary>
        /// <value>The name of the category.</value>
        public string Name { get; set; }

        /// <summary>
        /// Gets the name of the.
        /// </summary>
        /// <value>
        /// The name of the localized.
        /// </value>
        public string LocalizedName
        {
            get
            {
                return StringHelpers.ParseDictionaryItem(this.Name);
            }
        }

        /// <summary>
        /// Gets or sets the description.
        /// </summary>
        /// <value>The category description.</value>
        public string Description { get; set; }

        /// <summary>
        /// Gets the descr of the localized.
        /// </summary>
        /// <value>
        /// The name of the localized.
        /// </value>
        public string LocalizedDescription
        {
            get
            {
                return StringHelpers.ParseDictionaryItem(this.Name + "_Description", this.Description);
            }
        }

        /// <summary>
        /// Gets or sets the sort order.
        /// </summary>
        /// <value>The sort order.</value>
        public int SortOrder { get; set; }

        /// <summary>
        /// Gets or sets a value indicating whether this <see cref="Category"/> is selectable.
        /// </summary>
        /// <value><c>True</c> if selectable; otherwise, <c>false</c>.</value>
        public bool Selectable { get; set; }

        /// <summary>
        /// Gets or sets a value indicating whether this <see cref="Category"/> is enabled.
        /// </summary>
        /// <value><c>True</c> if enabled; otherwise, <c>false</c>.</value>
        public bool Enabled { get; set; }

        /// <summary>
        /// Gets a value indicating whether this instance has children.
        /// </summary>
        /// <value>
        /// <c>true</c> if this instance has children; otherwise, <c>false</c>.
        /// </value>
        public bool HasChildren { get; internal set; }

        /// <summary>
        /// Gets a value indicating whether this instance is a top level category.
        /// </summary>
        /// <value>
        /// <c>True</c> if this instance is a top level category; otherwise, <c>false</c>.
        /// </value>
        public bool IsTopLevel
        {
            get
            {
                return !this.ParentID.HasValue;
            }
        }

        /// <summary>
        /// Gets or sets the parent category ID.
        /// </summary>
        /// <value>
        /// The ID of the parent category.
        /// </value>
        public int? ParentID { get; set; }

        /// <summary>
        /// Gets the parent category.
        /// </summary>
        /// <value>The parent category.</value>
        public Category Parent 
        { 
            get
            {
                if (this.ParentID.HasValue && this.ParentID.Value > 0)
                    return new CategoryRepository().GetCategory(this.ParentID.Value);
                else
                    return null;
            }
        }

        /// <summary>
        /// Gets or sets the child categories.
        /// </summary>
        /// <value>The child categories.</value>
        public ICollection<Category> Children
        {
            get
            {
                if (this.HasChildren)
                    return new CategoryRepository().GetCategories(this.ID).ToList();
                else
                    return new List<Category>();
            }
        }

        /// <summary>
        /// Saves the current instance.
        /// </summary>
        public void Save()
        {
            bool isExistingCategory = this.ID > 0;

            CategoryRepository repo = new CategoryRepository();

            if (!isExistingCategory)
                repo.Add(this);
            else
                repo.Update(this);
        }

        /// <summary>
        /// Deletes the current instance.
        /// </summary>
        /// <returns>True if the category was deleted; otherwise false.</returns>
        public bool Delete()
        {
            bool isDeleted = false;
            bool isExistingCategory = this.ID > 0;

            if (isExistingCategory)
            {
                CategoryRepository repo = new CategoryRepository();
                
                repo.Delete(this);

                isDeleted = true;
            }

            return isDeleted;
        }

        /// <summary>
        /// Creates a new object that is a copy of the current instance.
        /// </summary>
        /// <returns>
        /// A new object that is a copy of this instance.
        /// </returns>
        public object Clone()
        {
            Category newCategory = new Category();

            newCategory.Name = this.Name.Clone() as string;
            newCategory.Description = this.Description.Clone() as string;
            newCategory.Enabled = this.Enabled;
            newCategory.Selectable = this.Selectable;
            newCategory.ParentID = this.ParentID;
            newCategory.HasChildren = this.HasChildren;

            return newCategory;
        }

        public bool IsDescendantOf(Category category)
        {
            if (this.ParentID.HasValue && this.ParentID.Value.Equals(category.ID))
            {
                return true;
            }
            else if (this.ParentID.HasValue && this.ParentID.Value > 0)
            {
                return this.Parent.IsDescendantOf(category);
            }

            return false;
        }
    }
}
